package object2D;

import context.*;

import byggeTegner.ByggeTegner;
import byggeTegner.DrawPanel;
import model2D.Model2D;
import object3D.Vindu;

import geometry2D.MetricPoint2D;
import geometry2D.Projection2D;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.json.JSONException;
import org.json.JSONObject;

import util.FillStyle;
import util.StrokeStyle;
import util.Util;
import util.Util2;

//***************************************************************************
//*** CLASS: VinduProjection
//***************************************************************************
public class VinduProjection extends BlockProjection implements Context.Constants
{ //private static final boolean DEBUG=true; // Overriding Context.Constants.DEBUG
  static final String TAG="object2D.VinduProjection";
  static final String TYPE="Vindu";

  protected Vindu getVindu() { return((Vindu)block); }
	
  // *************************************************************************
  // *** CONSTRUCTOR: VinduProjection
  // *************************************************************************
  public VinduProjection(Model2D objectModel,Vindu vindu,int type,int direction,Color color,float opacity)
  throws JSONException
  { super(objectModel,vindu,type,direction,color,opacity); }
  
  public VinduProjection(Model2D objectModel,JSONObject jsonObject) throws JSONException
//  { super(objectModel,jsonObject.getString("id"));
  { super(objectModel,jsonObject);
    if(DEBUG) Log.d(TAG,"decodeSVG: jsonObject="+jsonObject);
    this.fill=new FillStyle(jsonObject);
    this.stroke=new StrokeStyle(jsonObject);
//    boolean closed=jsonObject.optBoolean("closed",false);
//    JSONArray d=jsonObject.getJSONArray("d");
//    //if(DEBUG) Log.d(TAG,"PathObject.decodeSVG: name="+name+", d="+d);
//    clearPointSet();
//    for(int i=0;i<d.length();i++)
//    { JSONArray p=d.getJSONArray(i);
//      add(new MetricPoint2D(p));
//    }
//    setClosedPath(closed);
  }

  public JSONObject toJSONObject() throws JSONException
  { JSONObject jsonObject=new JSONObject();
    jsonObject.put("type",TYPE);
    jsonObject.put("id",getIdent());
//    jsonObject.put("closed",getClosedPath());  
//    jsonObject.put("d",getD());
    jsonObject.put("fill",fill.encode());
    jsonObject.put("stroke",stroke.encode());
	return(jsonObject);
  }


  // *************************************************************************
  // *** METHOD: paint
  // *************************************************************************
  public void paint(Graphics2D g,DrawPanel drawPanel)
  { switch(type)
    { case FASADE: paintFasade(g,drawPanel); break;
      case SNITT: paintSnitt(g,drawPanel); break;
      default: super.paint(g,drawPanel);
    }  
  }

  // *************************************************************************
  // *** METHOD: paintFasade
  // *************************************************************************
  private void paintFasade(Graphics2D g,DrawPanel drawPanel)
  { Projection2D r=getVindu().toProjection2D(direction);
    switch(direction)
    { case NORTH: tegnVinduFasade(g,r,color); break;
      case SOUTH: tegnVinduFasade(g,r,color); break;
      case EAST: tegnVinduFasade(g,r,color); break;
      case WEST: tegnVinduFasade(g,r,color); break;
//      case ABOVE: drawProjectionAbove(g,r,color); break;
//      case BELOW: drawProjectionBelow(g,r,color); break;
      default: super.paint(g,drawPanel);
    }  
  }

  // *************************************************************************
  // *** METHOD: paintSnitt
  // *************************************************************************
  private void paintSnitt(Graphics2D g,DrawPanel drawPanel)
  { Projection2D r=getVindu().toProjection2D(direction);
    switch(direction)
    { //case NORTH: tegnVinduFasade(g,r,color); break;
      //case SOUTH: tegnVinduFasade(g,r,color); break;
      //case EAST: tegnVinduFasade(g,r,color); break;
      //case WEST: tegnVinduFasade(g,r,color); break;
      case ABOVE: drawHorisontalCut(g,r,color); break;
      // case BELOW: drawProjectionBelow(g,r,color); break;
      default: super.paint(g,drawPanel);
    }  
  }
      
  private void drawHorisontalCut(Graphics2D g,Projection2D r,Color c)
  { double vinduTykkelse=0.05;
    Util.fill(g,r,Color.blue,opacity);//.white);
    if(r.width>r.height)
    { Util.fillRect(g,r.x,r.y-0.05,r.width,r.height+0.10,Color.white,opacity);
      Util.drawRect(g,r.x,r.y+r.height/2-vinduTykkelse/2,r.width,vinduTykkelse,opacity);
      if(TEGN_VINDU_DIM)
      { String str="B"+(int)(getVindu().width*10)+"/H"+(int)(getVindu().height*10);
        Util.label(g,str,r.x+r.width/2,r.y+r.height/3);
      }
    }
    else
    { Util.fillRect(g,r.x-0.05,r.y,r.width+0.10,r.height,Color.white,opacity);
      Util.drawRect(g,r.x+r.width/2-vinduTykkelse/2,r.y,vinduTykkelse,r.height,opacity);
      if(TEGN_VINDU_DIM)
      { String str="B"+(int)(getVindu().depth*10)+"/H"+(int)(getVindu().height*10);
        Util.label(g,str,r.x+r.width/2,r.y+r.height/2);
      }
    }
  }

  private void tegnVinduFasade(Graphics2D g,Projection2D r0,Color c)
  {
    Color vindusRammeFarge=Color.white;
    Color glassFarge=Util.glassFarge;
   
    // Tegn Vindusramme
    Util.fill(g,r0,vindusRammeFarge,opacity);
    
    // Tegn glasset
    double innskudd=0.08; //0.07;
    Projection2D r=new Projection2D(r0.x+innskudd,r0.y+innskudd,r0.width-2*innskudd,r0.height-2*innskudd);
    Util.fill(g,r,glassFarge,opacity);
    Util.draw(g,r,opacity);
    double corr=0.01;
    Projection2D r1=new Projection2D(r.x+corr,r.y+corr,r.width-2*corr,r.height-2*corr);
    Util.draw(g,r1,opacity);

    // Tegn evt. sprosse
    int nFag=getVindu().nRam;
    if(nFag>1)
    { // Tegn horisontal sprosse
      double sprossHeight=0.02;
      double y1=r.y+r.height/2; // XXX: Ad'hoc
      Util.fillRect(g,r.x,y1-sprossHeight,r.width,2*sprossHeight,vindusRammeFarge,opacity);
      Util.drawRect(g,r.x,y1-sprossHeight,r.width,2*sprossHeight,opacity);
      
      // Tegn vertikale sprosser
      for(int i=1;i<nFag;i++)
      { double sprossWidth=0.04;
        double x=r.x+r.width*i/nFag;
        Util.fillRect(g,x-sprossWidth,r.y,2*sprossWidth,r.height,vindusRammeFarge,opacity);
        Util.drawRect(g,x-sprossWidth,r.y,2*sprossWidth,r.height,opacity);
      }
    }

    // Tegn omramming
    if(getVindu().omramming)
    { double x=r0.x;
      double y=r0.y;
      double width=r0.width;
      double height=r0.height;
      double ramme=0.05;//8;
      double utskudd=0.05;//5;
      Util.fillRect(g,x-(ramme+utskudd),y-ramme,width+2*(ramme+utskudd),ramme,omrammingFarge,opacity);
      Util.drawRect(g,x-(ramme+utskudd),y-ramme,width+2*(ramme+utskudd),ramme,opacity);
   
      Util.fillRect(g,x-ramme,y,ramme,height,omrammingFarge,opacity);
      Util.drawRect(g,x-ramme,y,ramme,height,opacity);
    
      Util.fillRect(g,x+width,y,ramme,height,omrammingFarge,opacity);
      Util.drawRect(g,x+width,y,ramme,height,opacity);
    
      Util.fillRect(g,x-(ramme+utskudd),y+height,width+2*(ramme+utskudd),ramme,omrammingFarge,opacity);
      Util.drawRect(g,x-(ramme+utskudd),y+height,width+2*(ramme+utskudd),ramme,opacity);
    } else Util.draw(g,r0,opacity);
    
    // Tegn Vindus-dimensjon
    if(TEGN_VINDU_DIM)
    { String str="B"+(int)(r0.width*10)+"/H"+(int)(r0.height*10);
      Util.label(g,str,r.x+r.width/2,r.y+r.height/2);
    }

  }
  
  // ****************************************************************
  // *** INNER CLASS: EditGeneralPanel
  // ****************************************************************
  public JPanel getEditGeneralPanel(String title)
  { return(new EditGeneralPanel(title)); }
  private class EditGeneralPanel extends JPanel
  { static final long serialVersionUID=0; // AD'HOC
    private JTextField identField;
    private JButton strokeButton;
    private JButton fillButton;
      
    public void paint(Graphics g)
    { if(DEBUG) Log.d(TAG,"EditGeneralPanel.paint: ");
      identField.setText(getIdent());
      strokeButton.setBackground(stroke.getColor());
      fillButton.setBackground(fill.getColor());
  	  super.paint(g);  
    }
    	
    public EditGeneralPanel(String title)
    { setBorder(Util2.getTitleBorder(title));
      if(numberOfPoints()==4) // Firkant
      { setPreferredSize(new Dimension(350,120));//140));
        setLayout(new GridLayout(6,2));
      }
      else
      { setPreferredSize(new Dimension(350,120));
        setLayout(new GridLayout(5,2));
      }
      add(new JLabel("       Ident:"));
      identField=new JTextField(getIdent());
      identField.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { setIdent(identField.getText()); }
      });
      add(identField);
      fillButton=addEditFillButton(this,true);
      strokeButton=addEditStrokeButton(this,true);
        
      JCheckBox closedBox=new JCheckBox("Closed Path",null,getClosedPath());
      closedBox.addActionListener(new ActionListener()
      { public void actionPerformed(ActionEvent e)
        { setClosedPath(!getClosedPath());
          ByggeTegner.repaint();        	
        }
      });
      add(closedBox);
      add(new JLabel(" ")); // Space only
      
      if(numberOfPoints()==4)
      { JButton parallelogramButton=new JButton("Adjust Parallelogram");
//      parallelogramButton.setBackground(fill.getColor());
        parallelogramButton.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e) { ensureParallelogram(); } });
        add(parallelogramButton);
        
        JButton rectangleButton=new JButton("Adjust Rectangle");
//      rectangleButton.setBackground(fill.getColor());
        rectangleButton.addActionListener(new ActionListener()
        { public void actionPerformed(ActionEvent e) { ensureRectangle(); } });
        add(rectangleButton);
      }
    }
  }
  
  private void ensureParallelogram()
  { if(this.numberOfPoints()==4)
    { MetricPoint2D p0=getMapLocation(0);
      MetricPoint2D p1=getMapLocation(1);
      MetricPoint2D p2=getMapLocation(2);
      MetricPoint2D p3=getMapLocation(3);
      double dx=p1.getX()-p0.getX();
      double dy=p1.getY()-p0.getY();
      p3.setX(p2.getX()-dx);
      p3.setY(p2.getY()-dy);
    }
  }
  
  private void ensureRectangle()
  { if(numberOfPoints()==4)
    { MetricPoint2D p0=getMapLocation(0);
      MetricPoint2D p1=getMapLocation(1);
      MetricPoint2D p2=getMapLocation(2);
      double dx=p1.getX()-p0.getX();
      double dy=p1.getY()-p0.getY();
      double a=p2.getY()-p1.getY();      
      double b=dy/dx*a;
      p2.setX(p1.getX()-b);
      ensureParallelogram();
    }
  }

}